﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Media.Media3D;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Xml;
using Microsoft.Samples.Channels.ChunkingChannel;

namespace CrazyClient
{
    /// <summary>
    /// Interaction logic for ClientControl.xaml
    /// </summary>
    /// 
    [ServiceBehavior(
    InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple
    )]
    public partial class ClientControl : UserControl, IBaseListener
    {
        public ClientControl()
        {
            InitializeComponent();
            _displays = new Dictionary<Guid, Display>();
            _displayWindows = new Dictionary<Guid, ViewerWindow>();
            _assetHandler = new AssetHandler();
        }
        Dictionary<Guid, ViewerWindow> _displayWindows;
        Dictionary<Guid, Display> _displays;
        AssetHandler _assetHandler;
        public AssetHandler AssetHandler
        {
            get
            {
                return _assetHandler;
            }
        }
        #region IBaseListener Members

        public bool TryConnect()
        {
            textBox2.Text += "\n\rConnection Success\n\r";
            return true;
        }

        public DisplayInfoList GetDisplayInfo()
        {
            return new DisplayInfoList();
        }

        public Dictionary<Guid, Display> GetCurrentDisplays()
        {
            return Displays;
        }

        public Display AddFullScreenDisplay(string deviceName)
        {
            Point position = new Point(0, 0);
            foreach (System.Windows.Forms.Screen a in System.Windows.Forms.Screen.AllScreens)
            {
                if (a.DeviceName == deviceName)
                {
                    position.X += a.Bounds.X;
                    position.Y += a.Bounds.Y;
                }
            }
            Display display = new Display();
            display.DeviceName = deviceName;

            ViewerWindow displayWindow = new ViewerWindow();
            displayWindow.Owner = (Window)((Grid)((StackPanel)this.Parent).Parent).Parent;
            Displays.Add(display.Guid, display);
            DisplayWindows.Add(display.Guid, displayWindow);

            displayWindow.Maximize(deviceName);
            displayWindow.Show();
            return display;
        }
        public Display AddDisplay(string deviceName, Point position, Size size)
        {
            foreach (System.Windows.Forms.Screen a in System.Windows.Forms.Screen.AllScreens)
            {
                if (a.DeviceName == deviceName)
                {
                    position.X += a.Bounds.X;
                    position.Y += a.Bounds.Y;
                }
            }
            Display display = new Display();

            display.DeviceName = deviceName;
            ViewerWindow displayWindow = new ViewerWindow();
            displayWindow.Owner = (Window)((Grid)((StackPanel)this.Parent).Parent).Parent;
            Displays.Add(display.Guid, display);
            DisplayWindows.Add(display.Guid, displayWindow);

            displayWindow.Top = position.Y;
            displayWindow.Left = position.X;
            displayWindow.Width = size.Width;
            displayWindow.Height = size.Height;

            displayWindow.Show();

            return display;
        }
        public void ModifyDisplay(Guid key, Point position, Size size, bool isFullScreen)
        {
            string deviceName = Displays[key].DeviceName;
            foreach (System.Windows.Forms.Screen a in System.Windows.Forms.Screen.AllScreens)
            {
                if (a.DeviceName == deviceName)
                {
                    position.X += a.Bounds.X;
                    position.Y += a.Bounds.Y;
                }
            }

            DisplayWindows[key].Left = position.X;
            DisplayWindows[key].Top = position.Y;
            DisplayWindows[key].Height = size.Height;
            DisplayWindows[key].Width = size.Width;
            if (isFullScreen)
                DisplayWindows[key].Maximize(deviceName);

        }
        public void LoadXaml(ViewerWindow d, string xaml, string fileName)
        {
            ParserContext pc = new ParserContext();
            pc.XmlnsDictionary.Add("x", "http://schemas.microsoft.com/winfx/2006/xaml");
            pc.XmlnsDictionary.Add("", "http://schemas.microsoft.com/winfx/2006/xaml/presentation");
            pc.XmlnsDictionary.Add("c", "clr-namespace:CrazyClient;assembly=CrazyClient");
            pc.XmlnsDictionary.Add("fx", "clr-namespace:LearnWPF.Effects;assembly=LearnWPF.Effects");
            pc.BaseUri = new Uri(_assetHandler.AssetPath + fileName.Remove(fileName.LastIndexOf("/")));

            object de = XamlReader.Parse(xaml, pc);
            if (de is SetData)
                ((SetData)de).Data = d.viewer1.Data;
            if (de is LyricPanel)
                ((LyricPanel)de).SetParent(d.viewer1);
            if (de is Visual3D)
                d.viewer1.xamlContent.Children.Add((Visual3D)de);
            else if (de is UIElement)
            {

                d.viewer1.FlatPanel.Children.Add((UIElement)de);
                if (de is FrameworkElement)
                    ((FrameworkElement)de).Margin = new Thickness(0);
                ((FrameworkElement)de).UpdateLayout();
            }
        }
        public void LoadXaml(ViewerWindow d, List<string> xaml, string fileName)
        {
            foreach (string s in xaml)
                LoadXaml(d, s, fileName);
        }
        public void SendMidiMessage(MidiMessage m)
        {
            foreach (ViewerWindow d in DisplayWindows.Values)
            {
                d.viewer1.Data["Test1"] = (Double)m.Data2 / 1280;
                d.viewer1.Data["Test2"] = (Double)m.Data2;
                // d.viewer1.Background = new SolidColorBrush(Color.FromArgb(255, 0, 0, (byte)(m.Data2 * 2)));
            }
        }
        public void RemoveDisplay(Display display)
        {
            throw new NotImplementedException();
        }

        public void ResetDisplay(Display display)
        {
            throw new NotImplementedException();
        }

        #endregion
        public void SongOverride(bool activate)
        {
            int i = 0;
            if (activate)
                i = 1;
            foreach (ViewerWindow d in DisplayWindows.Values)
            {
                d.viewer1.Data["SongOverride"] = i;
            }
        }
        public void StartClient(string clientUri)
        {
            textBox2.Text += "Starting Client on: " + clientUri + "\n\r";
            ServiceHost svcHost = new ServiceHost(this, new Uri(clientUri));
            try
            {
                XmlDictionaryReaderQuotas quotas = new XmlDictionaryReaderQuotas();
                quotas.MaxStringContentLength = 6553500;

                // Check to see if the service host already has a ServiceMetadataBehavior
                ServiceMetadataBehavior smb = svcHost.Description.Behaviors.Find<ServiceMetadataBehavior>();
                //// If not, add one
                if (smb == null)
                    smb = new ServiceMetadataBehavior();
                //smb.HttpGetEnabled = true;
                smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
                svcHost.Description.Behaviors.Add(smb);
                //// Add MEX endpoint
                svcHost.AddServiceEndpoint(
                  ServiceMetadataBehavior.MexContractName,
                  MetadataExchangeBindings.CreateMexTcpBinding(),
                  "mex"
                );

                NetTcpBinding portsharingBinding = new NetTcpBinding();
                portsharingBinding.ReaderQuotas = quotas;
                portsharingBinding.ReaderQuotas.MaxStringContentLength = 6553500;
                portsharingBinding.MaxReceivedMessageSize = 6553500;

                svcHost.AddServiceEndpoint(typeof(IBaseListener), portsharingBinding, "");

                TcpChunkingBinding tcpchunkbind = new TcpChunkingBinding();

                svcHost.AddServiceEndpoint(typeof(IBaseListener), tcpchunkbind, "ep1");
                svcHost.Open();
                textBox2.Text += "Client started on: " + clientUri + "\n\r";
            }

            catch (Exception commProblem)
            {
                Console.WriteLine("There was a communication problem. " + commProblem.Message);
                Console.Read();
            }
            AssetHandler.Start(clientUri);
        }
        public void SendData(string name, int value)
        {
            foreach (ViewerWindow d in DisplayWindows.Values)
            {
                d.viewer1.Data[name] = value;
            }
        }
        public void SendDataString(string name, string value)
        {
            foreach (ViewerWindow d in DisplayWindows.Values)
            {
                d.viewer1.Data[name] = value;
            }
        }
        public Dictionary<Guid, Display> Displays
        {
            get { return _displays; }
        }
        public Dictionary<Guid, ViewerWindow> DisplayWindows
        {
            get
            {
                return _displayWindows;
            }
        }
        public bool AssetsNeedsUpdate(string filename, DateTime lastUpdate)
        {
            return AssetHandler.AssetsNeedsUpdate(filename, lastUpdate);
        }
        public void AssetUpdate(AssetSendSongData assetSongSendData)
        {
            AssetHandler.AssetUpdate(assetSongSendData.fileName, assetSongSendData.lastUpdate, assetSongSendData.data);
        }
        public void SongLoad(string fileName)
        {
            SongAsset xml = AssetHandler.GetSongAsset(fileName);
            foreach (ViewerWindow d in DisplayWindows.Values)
            {
                LoadXaml(d, xml.ScreenAll, fileName);
                if (d.viewer1.Data.ContainsKey("Uses3D"))
                    d.viewer1.Uses3D = d.viewer1.Data["Uses3D"].ToString()=="1";
            }
        }
        public void SongUnload()
        {
            foreach (ViewerWindow d in DisplayWindows.Values)
            {
                d.viewer1.xamlContent.Children.Clear();
                d.viewer1.FlatPanel.Children.Clear();
                d.viewer1.Data.Clear();
                d.viewer1.Data.Add("SongOverride", 0);
            }
        }


    }
}